Update file type from lua to luau and split out WhileHasComponents me… - #30
Update file type from lua to luau and split out WhileHasComponents me…#30Raild3x wants to merge 24 commits into
Conversation
There was a problem hiding this comment.
Pull Request Overview
This pull request refactors the component lifecycle utility functions by splitting the original WhileHasComponent method into two distinct methods: one for handling single components and another for handling multiple components. This improves type safety and API clarity while maintaining backward compatibility.
- Split
WhileHasComponentinto separate methods for single and multiple component handling - Added new
WhileHasComponentsmethod with improved documentation and examples - Updated deprecated
ForEachSiblingmethod to automatically route to appropriate methods
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
Expanded the Component module with comprehensive documentation covering lifecycle, edge cases, and extension system. Improved robustness for construction and start/stop phases, including cancellation and error handling during yields, rapid reparenting, and memory management. Added internal helper documentation, clarified extension method binding, and enhanced cleanup logic in Destroy. Minor code style and clarity improvements throughout.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 2 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Enhanced error messages during component construction and added warnings for construction cancellation. Improved validation in WhileHasComponents to ensure all elements are valid component classes. Adjusted cleanup order in Destroy and TryDeconstructComponent to ensure construction locks are always cleared.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 2 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Rewrote the component construction flow in Component:_instantiate to use a cancellable Promise, improving handling of ancestry changes and construction cancellation. Added detailed phase comments and improved error handling and cleanup logic. Also added and clarified assertions in WhileHasComponent, WhileHasComponents, and ForEachSibling for better API usage validation. Minor doc and formatting improvements throughout.
Reworked component lifecycle execution to a sync-first flow that only creates Promises when hooks actually yield, replacing the old Promise-chain driver. This also switches pending construction tracking to explicit cancel callbacks, preserves teardown signal delivery by deferring class janitor destruction until all teardowns finish, and reuses class-level extension resolution when instance variance is not needed. On the query side, this adds invalidation-backed caches, memoized sub-query evaluation in `get()`, split positive-candidate checks from the rest of matching, and replaces per-attribute janitor fanout with a single filtered `AttributeChanged` connection per candidate to reduce activation overhead. Tests/types were updated to match the API and behavior changes, including removal of sibling-binding coverage from the deleted spec.
Refactors `Query` to use copy-on-write builder methods (`with`, `anyOf`, `without`, `withAttribute`, `where`) so queries are immutable and chains can branch safely. Adds compiled query plans, requirement selectivity ordering, and cached structural signatures to avoid repeated requirement graph work. `Query` activation now interns engines by signature so equivalent queries share one reactive engine, and matched instances are tracked with a sparse-set (`matched` + `matchedList`) for O(1) membership updates and fast cloning. `get()` now has a live-engine fast path and a much narrower seeded enumeration strategy (class/tag/query/classlike) with optional tag sizing/probe-set optimization, reducing per-candidate overhead significantly. Tests were updated to validate copy-on-write branching behavior instead of self-referential mutation behavior.
Moves construction/destruction logic (_tryConstruct, _tryDeconstruct, GetLifecycleStatus, Destroy internals) from init.luau into Lifecycle.luau, exposing Request, Release, GetPhase, and DestroyClass. Adds construction-request tests covering dedup, same-frame retag, mid-construct cancel, unpublished supersede, and destroy-while-tearing-down. Also removes classWith type function, Connection type, Registry.Get, Query.withProperty, and the scratchpad file.
Moves the cross-class instance/component registry from `Registry.luau` into `Lifecycle.luau` and exposes it as `Lifecycle.GetAllForInstance`, then updates `Component.GetAllComponentsForInstance` to use that API. This keeps registration/unregistration logic at the lifecycle tracking points and removes the extra module. Adds lifecycle-focused tests to verify cross-class aggregation, post-construction visibility, and cleanup during teardown.
Switch class query checks from component-phase probing to a lifecycle-owned started sparse set (`startedInstances`/`startedList`) so started membership is tracked at start/teardown transitions and reused directly by query planning, seeding, and trivial fast paths. This also updates `Has` to use started membership, adds `Query:iter()` for allocation-free iteration when observed, and expands query tests to cover `iter()` behavior plus constructing/stopped exclusion in cold `GetMatches`.
Introduces `Query:contains`, `Query:count`, and `Query:first` as one-shot read APIs alongside `get`/`iter`, with docs and type exports updated accordingly. Refactors cold-read logic into shared helpers (`_singleSource`, `_staticSub`, `_collect`) so `get` reuses the same candidate planning and sub-query memoization while enabling early-exit scans for `first` and allocation-free counting. Adds query spec coverage for cold vs observed behavior and join queries to ensure parity with `GetMatches` semantics.
Extended Component.Query with `:withProperty(...)` matching (existence, explicit nil, value, or predicate) and reactive property-change re-evaluation via `GetPropertyChangedSignal`. Added `:observeUnyielding(...)` for inline, no-yield dispatch with loud contract-violation reporting on yield/error, plus shared observer attachment/dispatch internals and signature/planning updates for property clauses. Also updated tests to cover property matching and unyielding observer behavior, and aligned component type surfaces by replacing `CreateFromInstance` with `GetOrCreateFromInstance`, removing `Has` from `TypedClass`, and dropping the unused internal `PromiseLike` type.
Introduces `Query:track()` as a lightweight way to keep a query’s match set live without observer callbacks, returning a `QueryConnection` with idempotent disconnect behavior. This enables cheap repeated reads (`get`/`iter`/`count`/`first`/`contains`) while tracked and reuses the same reactive engine as observers. Adds query tests for live add/remove maintenance, disconnect fallback to cold reads, and engine sharing between tracked and observed query shapes. Also updates a lifecycle race test to use `GetOrCreateFromInstance`, and exports `Janitor`/`Promise` types in `Types.luau` while switching local requires there to package-relative paths.
Move misplaced `@within` tags onto the correct functions, convert a single-line deprecated comment to proper moonwave block, and fix parameter name mismatches in doc blocks (`task` → `task_`, `reason` → `_reason`).
This pull request refactors and improves the component lifecycle utility functions in
lib/component/src/init.luau. The main focus is to clarify the API by splitting the handling of single and multiple component classes, improving type safety, and updating documentation. It also introduces a newWhileHasComponentsmethod for handling multiple components and updates the deprecatedForEachSiblingmethod for better backward compatibility.API improvements and refactoring:
WhileHasComponentmethod into two:WhileHasComponent(for a single component class) and a newWhileHasComponents(for an array of component classes), providing clearer and safer APIs for each use case. [1] [2]Documentation and deprecation:
ForEachSiblingmethod to warn users to use the new methods and to automatically route calls to the appropriate method for backward compatibility.…thod